﻿#region Using
using System;
using System.Xml;
using System.Threading;
using AifMessageHeaderEditor.Lib.Data.MessageDocument.Message;
using AifMessageHeaderEditor.Lib.Data.MessageDocument.Message.Body;
using AifMessageHeaderEditor.Lib.Data.MessageDocument.Message.Header;
#endregion

namespace AifMessageHeaderEditor.Lib.Data.MessageDocument
{
    /// <summary>
    /// Handles the <c>XmlDocument</c> of the Aif-message
    /// </summary>
    public partial class MessageDocument : IDataBase
    {
        #region members and consts

        private const string FILE_EXCEPTION_READONLY = 
            "Please check that the file has no ReadOnly-attribute";

        protected MessageDataBase _bodyNode;
        protected MessageDataBase _headerNode;
        protected XmlDocument _xmlMessage = new XmlDocument();

        #endregion

        #region properties

        public MessageBodyData BodyNode
        {
            get { return (MessageBodyData) _bodyNode; }
        }

        public MessageHeaderData HeaderNode
        {
            get { return (MessageHeaderData)_headerNode; }
        }
        
        protected XmlNamespaceManager Namespaces
        {
            get
            {
                XmlNamespaceManager namespaces = new XmlNamespaceManager(_xmlMessage.NameTable);
                namespaces.AddNamespace(AppCommon.XML_NS,
                    AppCommon.AIF_NAMESPACE_DOCUMENTS);

                return namespaces;
            }
        }

        #endregion        

        #region constructor

        public MessageDocument()
        {
            _bodyNode = new MessageBodyData(null);
            _headerNode = new MessageHeaderData(null);
        }

        #endregion

        #region methods : document

        internal virtual void LoadXmlMessage(string filename)
        {
            const int RETRIES = 3;
            const int WAIT = 100;
            int tries = 0;
            
         retry:
            try
            {
                _xmlMessage.Load(filename);
                _bodyNode = new MessageBodyData(SelectXmlBodyNode());
                _headerNode = new MessageHeaderData(SelectXmlHeaderNode());
                NotifyChanges();
            }
            catch (Exception ex)
            {
                if (++tries > RETRIES)
                    throw new Exception("The file is locked: " + ex.Message, ex);
                Thread.Sleep(WAIT);

                goto retry;
            }
        }

        internal virtual void ResetMessage()
        {
            _xmlMessage = new XmlDocument();
            _bodyNode = new MessageBodyData(null);
            _headerNode = new MessageHeaderData(null);
            NotifyChanges();
        }

        internal void SaveXmlMessage(string filename)
        {
            try
            {
                _xmlMessage.Save(filename);
                NotifyChanges();

            }
            catch (System.UnauthorizedAccessException uaEx)
            {
                throw new System.Exception(FILE_EXCEPTION_READONLY, uaEx);
            }
        }

        public void NotifyChanges()
        {
            if (BodyNode != null)
                BodyNode.NotifyChanges();
            if (HeaderNode != null)
                HeaderNode.NotifyChanges();
        }

        #endregion

        #region methods : document + nodes

        public XmlNode SelectXmlHeaderNode(string element = "")
        {
            return AppCommon.SelectXmlHeaderNode(_xmlMessage, Namespaces, element);
        }

        public XmlNode SelectXmlBodyNode()
        {
            return AppCommon.SelectXmlBodyNode(_xmlMessage, Namespaces);
        }

        #endregion
    }
}